export {};

/**
 * unknown 是ts中一个特殊类型    any类型表示放弃了ts的类型检验
 * unknown 和 any 非常类型  但是是一个安全类型。
 * 任何类型都是unknown的子类型
 * 兼容性：unknown只能赋值给unknown 和 any
 *
 */

function sum(a: unknown, b: number) {
  // return a+b  error  unknown 类型不能计算
  if (typeof a === "number") {
    return a + b;
  }
  if (typeof a === "string") {
    return a + b;
  }
  return a as boolean;
}

//unknown任何类型做联合类型 都等于 unknown
type IN = unknown | number; // unknown

//unknown任何类型做交叉类型 都等于 其他类型
type IY = unknown & number; // number

//unknown 不支持keyof
type IA = keyof any; // string | number | symbol
type IU = keyof unknown; // never

// 应用场景
let data: unknown = JSON.parse("{name:1}"); //默认any  设置为unknown确保安全性
function isSchool(data: any): data is { name: string } {
  return data.name;
}
if (isSchool(data)) {
  data; // name :string
}

//  T= number  泛型默认值为number

type IK<T = number> = {
  [K in keyof T]: number;
};

type IT = IK<number>; // number

type IT1 = IK<unknown>; // {}

/*
  infer ts中可以自动推断类型 关键字 infer
*/

//取函数的返回值类型
function getUserInfo(name: string) {
  return { name: "", age: "" };
}
type ReturnType<T extends (...args: any[]) => void> = T extends (
  ...args: any[]
) => infer R
  ? R
  : never;
type MyReturnType = ReturnType<typeof getUserInfo>; // {name:string, age:string}

// 取函数的参数类型 场景： 不调用函数 取到函数的返回值类型
type Parameters<T extends (...args: any[]) => void> = T extends (
  ...args: infer R
) => void
  ? R
  : never;
type MyParameters = Parameters<typeof getUserInfo>; // [name:string]

// 取类的实例类型
class My {
  constructor(x: string) {}
}
type InstanceType<T extends { new (...args: any[]): void }> = T extends {
  new (...args: any[]): infer R;
}
  ? R
  : never;
type MyInstanceType = InstanceType<typeof My>; // My

// 获取构造函数将接受的参数类型
type ConstructorParameters<T extends { new (...args: any[]): void }> =
  T extends {
    new (...args: infer R): void;
  }
    ? R
    : never;
type MyConstructorParameterse = ConstructorParameters<typeof My>; // [x:string]
type P1 = MyConstructorParameterse[0]; //string

//  泛型推断 场景举例：将一个元组类型转化为一个联合类型

type Transfer<T> = T extends Array<infer R> ? R : never;
type MyTransfer = Transfer<[string, number, boolean]>; // string| number |boolean
